import React, { useEffect, useMemo, useRef } from "react"
import { Image, ScrollView, View } from "@tarojs/components"
import { Tabs } from "@taroify/core"
import styles from "./index.module.scss"
import GpContainer from "@/components/GpContainer"
import Taro, { useRouter, useDidShow } from "@tarojs/taro"
import { useSetState } from "@/utils/hooks"
import { getBaikeDetail } from "@/apis/yikao-community"
import { requestIsFullfilled } from "@/utils/request"
import clsx from "clsx"
import { BaikeRelationType } from "@/types/enum"
import { navigation } from "@/utils/router"
import { pageMapper, pageMapperCommunity } from "@/constants/pageMap"
import { ScrollViewProps } from "@tarojs/components/types/ScrollView"

type IState = {
  /** 选择的一级类目值 */
  firstValue?: number
  /** 选择的二级类目 */
  secondLevel?: IApiRelative.IGetBaikeDetail.BaikeDetailCategory
  detail: IApiRelative.IGetBaikeDetail.IResData
  scrollIntoViewId?: number
  currentActiveTab?: number
}
type IParams = {
  /**知识百科id */
  id: string
}
/**
 * @page 知识百科
 */
export default function ProfessionBaike() {
  const idPrefix = "third_"
  const router = useRouter<IParams>()
  useEffect(() => {
    fetchDetail()
  }, [])
  const [state, setState, stateRef] = useSetState<IState>(
    {
      detail: {
        categorys: []
      } as any
    },
    true
  )
  const updator = useRef<INullable<IFn>>(null)
  const secondLevelUpdation = useRef<IApiRelative.IGetBaikeDetail.BaikeDetailCategory>()
  const scrollTriggeredByFilterTap = useRef<boolean>(false)
  useDidShow(() => {
    if (secondLevelUpdation.current) {
      setState({ secondLevel: secondLevelUpdation.current })
      secondLevelUpdation.current = void 0
    }
  })
  async function fetchDetail() {
    try {
      Taro.showLoading({ title: "加载中" })
      const res = await getBaikeDetail({ id: router.params.id })
      Taro.hideLoading()
      if (requestIsFullfilled(res)) {
        const detail = res.data.data
        Taro.setNavigationBarTitle({ title: detail.title })
        setState({ detail })
        if (detail.categorys.length > 0) {
          const firstLevel = detail.categorys[0]
          handleFirstValueChange(firstLevel.value)
        }
      }
    } catch (error) {
      Taro.hideLoading()
    }
  }
  function handleFirstValueChange(activeKey: number, secondValue?: number) {
    setState({ firstValue: activeKey })
    const categorys = stateRef.current?.detail.categorys
    if (categorys && categorys.length > 0) {
      const finder = categorys.find(l => l.value === activeKey)
      if (finder && finder.children && finder.children.length > 0) {
        let i = 0
        if (secondValue) {
          const index = finder.children.findIndex(l => l.value === secondValue)
          if (index !== -1) {
            i = index
          }
        }
        const _secondLevel = finder.children[i]
        // 每次切换一级分类默认选中第一个有item的分类
        let scrollIntoViewId = -1
        if (_secondLevel.items && _secondLevel.items.length > 0) {
          scrollIntoViewId = _secondLevel.value
        } else if (_secondLevel.children && _secondLevel.children.length > 0) {
          scrollIntoViewId = _secondLevel.children[0].value
        }
        setState({
          secondLevel: _secondLevel,
          scrollIntoViewId,
          currentActiveTab: scrollIntoViewId
        })
      }
    }
  }
  function handleChooseSecond(_secondLevel: IApiRelative.IGetBaikeDetail.BaikeDetailCategory) {
    if (state.secondLevel?.value !== _secondLevel.value) {
      // 每次切换二级分类默认选中第一个有item的分类
      let scrollIntoViewId = -1
      if (_secondLevel.items && _secondLevel.items.length > 0) {
        scrollIntoViewId = _secondLevel.value
      } else if (_secondLevel.children && _secondLevel.children.length > 0) {
        scrollIntoViewId = _secondLevel.children[0].value
      }
      setState({ secondLevel: _secondLevel })
      updator.current = function () {
        setState({ scrollIntoViewId, currentActiveTab: scrollIntoViewId })
      }
    }
  }
  function runUpdator() {
    if (updator.current) {
      updator.current()
      updator.current = null
    }
  }
  function handleCategoryClick(value: number) {
    setState({ scrollIntoViewId: value, currentActiveTab: value })
    scrollTriggeredByFilterTap.current = true
  }
  const fuckMuGou = useRef<any>()
  /** 记录items位置 */
  const itemsPosition = useRef<Array<{ id: string; relativeTop: number; value: number }>>([])
  const { categoryList, secondLevelChildren, hasThirdLevelItems } = useMemo(() => {
    let _hasThirdLevelItems = false
    const _categoryList: IOptionLike<number>[] = []
    const _secondLevelChildren: IApiRelative.IGetBaikeDetail.BaikeDetailCategory[] = []
    if (state.secondLevel) {
      // Taro.showLoading({ title: "加载中...", mask: true })
      if (state.secondLevel.items && state.secondLevel.items.length > 0) {
        _categoryList.push({
          label: state.secondLevel.label,
          value: state.secondLevel.value
        })
        _secondLevelChildren.push(state.secondLevel)
      }
      if (state.secondLevel.children && state.secondLevel.children.length > 0) {
        _hasThirdLevelItems = true
        state.secondLevel.children.forEach(l => {
          if (l.items && l.items.length > 0) {
            _categoryList.push({
              label: l.label,
              value: l.value
            })
            _secondLevelChildren.push(l)
          }
        })
      }
      // 计算滚动位置
      if (_secondLevelChildren.length > 1) {
        clearTimeout(fuckMuGou.current)
        fuckMuGou.current = setTimeout(() => {
          // Taro.hideLoading()
          calcItemsPosition()
          itemsPosition.current = []
          runUpdator()
        }, 500)
      } else {
        itemsPosition.current = []
        runUpdator()
        // Taro.hideLoading()
      }
    } else {
      runUpdator()
    }
    return {
      hasThirdLevelItems: _hasThirdLevelItems,
      categoryList: _categoryList,
      secondLevelChildren: _secondLevelChildren
    }
  }, [state.secondLevel])
  /** 计算滚动位置 */
  function calcItemsPosition() {
    const query = Taro.createSelectorQuery()
    secondLevelChildren.forEach(l => {
      query.select(`#${idPrefix + l.value}`).boundingClientRect()
    })
    query.exec((rects: Taro.NodesRef.BoundingClientRectCallbackResult[]) => {
      console.info("[calcItemsPosition] rects: ", rects)
      if (rects.length === 0) return
      const relativeOffset = rects[0].top
      itemsPosition.current = rects.map((rect, index) => {
        return {
          id: rect.id,
          relativeTop: rect.top - relativeOffset,
          value: secondLevelChildren[index].value
        }
      })
      runUpdator()
    })
  }
  function handleItemClick(item: IApiRelative.IGetBaikeDetail.BaikeDetailDataItem) {
    // @reference: https://www.tapd.cn/42905076/bugtrace/bugs/view?bug_id=1142905076001013191
    item.learnerCount += 1
    if (stateRef.current!.secondLevel) {
      secondLevelUpdation.current = JSON.parse(JSON.stringify(stateRef.current!.secondLevel))
    }
    if (item.relationType === BaikeRelationType.Note) {
      navigation(pageMapperCommunity.NoteDetail, { id: item.relationId })
    } else if (item.relationType === BaikeRelationType.Article) {
      navigation(pageMapper.newsDetail, { id: item.relationId })
    }
  }
  function handleFuckScroll(ev: { detail: ScrollViewProps.onScrollDetail }) {
    if (scrollTriggeredByFilterTap.current) {
      scrollTriggeredByFilterTap.current = false
      return
    }
    if (itemsPosition.current.length === 0) return
    const { scrollTop } = ev.detail
    let index = -1
    for (let i = itemsPosition.current.length - 1; i >= 0; i--) {
      if (scrollTop >= itemsPosition.current[i].relativeTop) {
        index = i
        break
      }
    }
    if (index < 0) {
      index = 0
    }
    const activeValue = itemsPosition.current[index].value
    if (stateRef.current!.currentActiveTab === activeValue) return
    setState({ currentActiveTab: activeValue, scrollIntoViewId: -1 })
  }
  return (
    <GpContainer
      style={{
        height: "100vh"
      }}
      shareConfig={{
        title: state.detail.title
      }}
    >
      <View className={styles.ProfessionBaike}>
        <Tabs value={state.firstValue} onChange={value => handleFirstValueChange(value)}>
          {state.detail.categorys.map(first => (
            <Tabs.TabPane value={first.value} title={first.label}>
              <View className={styles.main}>
                {/* sider */}
                <View className={styles.sider}>
                  {/* 二级分类 */}
                  <ScrollView
                    style={{
                      height: "100%"
                    }}
                    scrollY
                  >
                    {first.children.map(second => (
                      <View
                        key={second.value}
                        onClick={() => handleChooseSecond(second)}
                        className={styles.siderItem}
                      >
                        <View
                          className={clsx(styles.siderItemInner, {
                            [styles.siderItemInnerActive]: state.secondLevel?.value === second.value
                          })}
                        >
                          {second.label}
                        </View>
                      </View>
                    ))}
                  </ScrollView>
                </View>
                {/* content */}
                <View className={styles.content}>
                  {/* 分类 */}
                  {hasThirdLevelItems && (
                    <View className={styles.categorysWrap}>
                      <ScrollView scrollX className={styles.categorys}>
                        {categoryList.map(l => (
                          <View
                            className={styles.categoryWrap}
                            key={l.value}
                            onClick={() => handleCategoryClick(l.value)}
                          >
                            <View
                              className={clsx(styles.category, {
                                [styles.categoryActive]: l.value === state.currentActiveTab
                              })}
                            >
                              {l.label}
                            </View>
                          </View>
                        ))}
                      </ScrollView>
                    </View>
                  )}
                  <View
                    className={clsx("flex-1 box-border h-0", {
                      "pt-24px": !hasThirdLevelItems
                    })}
                  >
                    <ScrollView
                      scrollY
                      style={{
                        height: "100%"
                      }}
                      scrollIntoView={idPrefix + state.scrollIntoViewId}
                      onScroll={handleFuckScroll}
                    >
                      {secondLevelChildren.map(third => (
                        <View
                          className={styles.cardItem}
                          key={third.value}
                          id={idPrefix + third.value}
                        >
                          <View className={styles.cardTitle}>{third.label}</View>
                          {third.items && third.items.length > 0 ? (
                            <View className={styles.cardList}>
                              {third.items.map(item => (
                                <View
                                  className={styles.cardListItem}
                                  key={item.id}
                                  onClick={() => handleItemClick(item)}
                                >
                                  <Image src={item.thumbnail} className={styles.image} />
                                  <View className={styles.cardListItemRight}>
                                    <View className={clsx(styles.cardListItemTitle)}>
                                      {item.displayTitle}
                                    </View>
                                    <View className={clsx(styles.cardListItemDesc)}>
                                      {item.learnerCount}人学习
                                    </View>
                                  </View>
                                </View>
                              ))}
                            </View>
                          ) : null}
                        </View>
                      ))}
                    </ScrollView>
                  </View>
                </View>
              </View>
            </Tabs.TabPane>
          ))}
        </Tabs>
      </View>
    </GpContainer>
  )
}
